package com.pic.mgt.haishin.executer;

import java.io.File;
import java.io.IOException;
import java.sql.Timestamp;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.springframework.dao.DataAccessException;
import org.springframework.dao.DuplicateKeyException;

import com.pic.mgt.IgxStatus;
import com.pic.mgt.dao.haishin.AppointedHaishinBusinessAsgmtActionDao;
import com.pic.mgt.haishin.executer.AsgmtFileProcess.AsgmtBuildResult;
import com.pic.mgt.log.IgxLog;
import com.pic.mgt.unit.Business;

public class AppointedHaishinActionNotifyHandler
						extends HaishinActionNotifyHandler {
	private AppointedHaishinBusinessAsgmtActionDao appointedHaishinBusinessAsgmtActionDao;
	
	/*
	 *  當在進行 建立指示檔 處理過程中，每完處理完一項端末
	 *  指示檔，就會觸發此方式通知。
	 */	
	@Override
	public boolean asgmtProcessNotify(Business business,
								   String terminal, File asgmtFile,
								   AsgmtBuildResult asgmtBuildResult) {
		
		/*System.out.println("Terminal: " + terminal);
		System.out.println("File: " + asgmtFile.getName());
		System.out.println("Result: " + asgmtBuildResult);	*/
		
		String resultStatus = null;
		
		if (asgmtBuildResult.equals(AsgmtBuildResult.AsgmtBuildComplete)) {
			// 正常完成一個端末的處理
			
			resultStatus = IgxStatus.HAISHIN_ASGMT_ACTION_COMPLETE;
			
			// ********************** Log **********************
			if (IgxLog.messageDetailsLog.isTraceMode()) {
				IgxLog.messageDetailsLog
						.trace(this, 
								"Business '{}' Asgmt file building process to terminal '{}' completed.",
								business.getUnitName(), terminal);
			}
			// ********************** Log **********************
			
			
			// 資料庫寫入
			// 資料庫新增 (table:appointed_haishin_business_asgmt_action)
			boolean isInsertSuccess = 
						doDBInsertBasic(business,
										terminal,
										asgmtFile,
										resultStatus);
			if (!isInsertSuccess) { return false; }
			
			
			// 產生 FILEOK 檔
			try {
				super.confirmationFileMaker.
							makeConfirmationFile(asgmtFile);
				
				// ********************** Log **********************
				if (IgxLog.messageDetailsLog.isTraceMode()) {
					IgxLog.messageDetailsLog.trace(this, "Generating confirmation file for transaction file '{}' to terminal '{}' completed.",
							asgmtFile.getName(),
								  terminal);
				}
				// ********************** Log **********************
			} catch (IOException e) {
				// ********************** Log **********************
				IgxLog.messageLog
						.error(
								this,
								"Creating confirmation file for transaction file '{}' in haishin business '{}' failed.",
								asgmtFile.getName(), business
										.getUnitName());
				// ********************** Log **********************
				
				return false;
			}
		}
		else if (asgmtBuildResult.equals(AsgmtBuildResult.IneffectiveTerminal)) {
			// 錯誤的端末
			
			resultStatus = IgxStatus.HAISHIN_ASGMT_ACTION_INEFFECTIVE_TERMINAL;
			
			// ********************** Log **********************
			IgxLog.messageLog.warn(this, 
					"SUDA-326 Asgmt file '{}' has been ignored because appointed haishin business '{}' assigned an ineffective terminal id '{}'.",
					asgmtFile.getName(), business.getUnitName(), terminal);
			// ********************** Log **********************
			
			// 資料庫寫入
			// 資料庫新增 (table:appointed_haishin_business_asgmt_action)
			boolean isInsertSuccess = 
						doDBInsertBasic(business,
										terminal,
										asgmtFile,
										resultStatus);
			if (!isInsertSuccess) { return false; }
		}
		
		return true;
	}
	
	private boolean doDBInsertBasic(Business business,
									String terminal,
									File asgmtFile,
									String resultStatus) {
		try {
			Map<String, Object> inserValuesMap = getDBInsertBasicValuesMap(business,
					terminal,
					asgmtFile,
					resultStatus);
			// throws DataAccessException
			this.appointedHaishinBusinessAsgmtActionDao.insertBasic(inserValuesMap);
		} catch (DuplicateKeyException e1) {
			//	若是在 Insert 資料時發生 Unique Key 重覆的例外
			
			/*
			 * 此種情況可能發生的情形是在，當配信處理過程中發生失敗而中斷，
			 * 導致 table 內已經存在多筆有執行成功的資料紀錄;或者是在進行重配信的情
			 * 況下才發生發生資料有重覆 insert 的情形。此時只需要更新 creating time.
			 */
			try {
				this.appointedHaishinBusinessAsgmtActionDao.
									updateCreatingTimeByAsgmtFilename(new Timestamp(new Date().getTime()),
															     asgmtFile.getName());
			} catch (DataAccessException e) {
				// ********************** Log **********************
				IgxLog.messageDetailsLog.error(this, e.getMessage());
				// ********************** Log **********************

				// ********************** Log **********************
				IgxLog.messageLog.error(this,
						"SUDA-224 Update haishin asgmt action record '{}' to database (table: {}) failed.",
						asgmtFile.getName(),
						this.appointedHaishinBusinessAsgmtActionDao.getTableName());
				// ********************** Log **********************

				return false;
			}
		} catch (DataAccessException e2) {
			// ********************** Log **********************
			IgxLog.messageDetailsLog.error(this, e2.getMessage());
			// ********************** Log **********************

			// ********************** Log **********************
			IgxLog.messageLog.error(this,
					"SUDA-225 Inert haishin asgmt action record '{}' to database (table: {}) failed.",
					asgmtFile.getName(),
					this.appointedHaishinBusinessAsgmtActionDao.getTableName());
			// ********************** Log **********************

			return false;
		}

		return true;
	}

	private Map<String, Object> getDBInsertBasicValuesMap(Business business,
			String terminal,
			File asgmtFile,
			String resultStatus) {
		Map<String ,Object> insertValuesMap = new HashMap<String, Object>();

		insertValuesMap.put(AppointedHaishinBusinessAsgmtActionDao._targetFile, business.getTargetFilename());
		insertValuesMap.put(AppointedHaishinBusinessAsgmtActionDao._unitName, business.getUnitName());
		insertValuesMap.put(AppointedHaishinBusinessAsgmtActionDao._terminalId, terminal);
		insertValuesMap.put(AppointedHaishinBusinessAsgmtActionDao._asgmtFilename, asgmtFile.getName());
		insertValuesMap.put(AppointedHaishinBusinessAsgmtActionDao._asgmtFilesize, asgmtFile.length());
		insertValuesMap.put(AppointedHaishinBusinessAsgmtActionDao._result, resultStatus);

		return insertValuesMap;
	}

	// --- getter and setter ---
	
	public void setAppointedHaishinBusinessAsgmtActionDao(
			AppointedHaishinBusinessAsgmtActionDao appointedHaishinBusinessAsgmtActionDao) {
		this.appointedHaishinBusinessAsgmtActionDao = appointedHaishinBusinessAsgmtActionDao;
	}
}
